/**
 * @apiDefine ApiError
 * @apiError (Error 4xx) {Object} error Error object
 * @apiError (Error 4xx) {String} error.message Error message
 * @apiError (Error 5xx) {Object} error Error object
 * @apiError (Error 5xx) {String} error.message Error message
 * description: api接口
 */
package api

import (
	"html/template"
	"net/http"

	"github.com/julienschmidt/httprouter"
	"github.com/justinas/alice"
	"learning.com/edu/app/middleware"
	"learning.com/edu/models"
	"learning.com/edu/utils/helper"
	"learning.com/edu/utils/mailer"
)

type Api struct {
	h 		   *helper.Helper
	middleware *middleware.Middleware
	config     *models.Config
	models     *models.Models
	mailer     *mailer.Mailer
	templateCache map[string] *template.Template
}

func New(h *helper.Helper, config *models.Config) (*Api, error) {
	models, err := models.NewModels(&config.Database, h)
	if err != nil {
		return nil, err
	}
	
	mailer := mailer.New(&config.Smtp)
	middleware := middleware.New(h, &config.Limiter, models)
	api := &Api{
		h: h,
		config: config,
		models: models,
		mailer: mailer,
		middleware: middleware,
	}

	api.templateCache, err = api.loadTemplateCache()
	if err != nil {
		return nil, err
	}
	return api, nil
}

func (api *Api) Version() string {
	return "v1"
}

/**
 * Routes:用于配置 HTTP 路由和中间件
 */
func (api *Api) Routes() http.Handler {
	router := httprouter.New()

	router.NotFound = http.HandlerFunc(api.h.NotFoundResponse)
	router.MethodNotAllowed = http.HandlerFunc(api.h.MethodNotAllowedResponse)

	// 添加路由
	api.utilsRoutes(router) // 公共路由
	api.userRoutes(router) // 用户路由
	api.htmlRoutes(router) // HTML 路由
	api.courseRoutes(router) // 课程路由
	api.businessRoutes(router) // 商家路由

	// 添加中间件
	standard := alice.New(
		api.middleware.Metrics,
		api.middleware.RecoverPanic,
		api.middleware.LogRequest,
		api.middleware.RateLimit,
		api.middleware.Authenticate,
	)

	return standard.Then(router)
}

/**
 * Routes:用于配置 HTTP 课程视频路由和中间件
 */
func (api *Api) CourseVideoRoutes() http.Handler {
	router := httprouter.New()

	router.NotFound = http.HandlerFunc(api.h.NotFoundResponse)
	router.MethodNotAllowed = http.HandlerFunc(api.h.MethodNotAllowedResponse)

	router.HandlerFunc(http.MethodGet, "/v1/course/video/:id", 
		api.middleware.RequireAuthenticatedUser(api.getVideoFile))

	standard := alice.New(
		api.middleware.RecoverPanic,
		api.middleware.LogRequest,
		api.middleware.RateLimit,
		api.middleware.Authenticate,
	)

	return standard.Then(router)
}